# -*- coding: utf-8 -*-

import os
import cgi
import urllib
import sys
import md5
import logging
import time

from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
from google.appengine.api import mail
from google.appengine.api import urlfetch
from google.appengine.api.urlfetch_errors import *
from google.appengine.api import users
from google.appengine.ext.db import Key
from google.appengine.ext.db import BadKeyError
from google.appengine.ext.webapp import template
from google.appengine.api import images

from xml.dom import minidom
from django.utils import simplejson
from time import strftime

from baseclass import BaseHandler
from model import Information
from model import NumberImage
     
class MainPage(BaseHandler):    
    def get(self):        
        values = {}
        self.outputTemplate(values, "main_view")
        
class RequestKeyPage(BaseHandler):
    myid = "agt2aXN1YWxjaGVja3IRCxILSW5mb3JtYXRpb24YAQw"
    mysecret = "agt2aXN1YWxjaGVja3ISCxILTnVtYmVySW1hZ2UY6QcM"
        
    # Validate if the user input numbers equals the numbers 
    # encoded in the picture
    # numbers: the user input
    # token: the token sent when requesting the picture
    def isTokenValid(self, numbers, token):
        try:            
            encrypt = md5.new()
            encrypt.update(token)
            encrypt.update(self.mysecret)   # Your secret given after signup
            md5token = encrypt.hexdigest().upper()
            logging.debug("Excepted:"+md5token+" Actual:"+numbers) 
            # HEX values A to F are mapped to numbers 0 to 5           
            for i in [0,1,2,3,4,5]:
                if md5token[i] == numbers[i]:
                    continue
                elif md5token[i] == 'A' and numbers[i] == '0':
                    continue
                elif md5token[i] == 'B' and numbers[i] == '1':
                    continue
                elif md5token[i] == 'C' and numbers[i] == '2':
                    continue
                elif md5token[i] == 'D' and numbers[i] == '3':
                    continue
                elif md5token[i] == 'E' and numbers[i] == '4':
                    continue
                elif md5token[i] == 'F' and numbers[i] == '5':
                    continue
                else:
                    return False
            return True
        except:
            return False
        
    def get(self):
        randomstr = self.request.remote_addr + str(time.time())
        values = {'mytoken': randomstr}
        self.outputTemplate(values, "signup_view")        
        
    def post(self):
        values = {}
        try:
            mytoken = self.request.get('mytoken')
            if not self.isTokenValid(self.request.get('numbers'), mytoken):
                raise "Invalid verification numbers"
            info = Information(name = self.request.get('name'),
                               secret = 'None')
            info.put()
            img = NumberImage(information=info)
            img.put()
            info.secret = str(img.key())
            info.put()
            values['id'] = info.key()
            values['secret'] = img.key()
            self.setCookie('id', values['id'])
            self.setCookie('secret', values['secret'])
            values['msg'] = "Please remember your id: "+str(values['id'])+" and your secret: "+str(values['secret'])
        except:
            values['msg'] = str(sys.exc_info())  
        finally:
            randomstr = self.request.remote_addr + str(time.time())
            values['mytoken'] = randomstr
            self.outputTemplate(values, "signup_view")  
            
class DisplayPage(BaseHandler):
    def createImage(self, img, token, secret):
        if token:      
            imgs = {}      
            encrypt = md5.new()
            encrypt.update(token)
            encrypt.update(secret)
            md5token = encrypt.hexdigest().upper()            
            logging.debug(token+"+"+secret+" md5: "+md5token)
            for i in [0,1,2,3,4,5]:
                digit = md5token[i]
                if digit == '0':
                    imgs[i] = img.img0
                elif digit == '1':
                    imgs[i] = img.img1
                elif digit == '2':
                    imgs[i] = img.img2
                elif digit == '3':
                    imgs[i] = img.img3
                elif digit == '4':
                    imgs[i] = img.img4
                elif digit == '5':
                    imgs[i] = img.img5
                elif digit == '6':
                    imgs[i] = img.img6
                elif digit == '7':
                    imgs[i] = img.img7
                elif digit == '8':
                    imgs[i] = img.img8
                elif digit == '9':
                    imgs[i] = img.img9
                elif digit == 'A':
                    imgs[i] = img.img0
                elif digit == 'B':
                    imgs[i] = img.img1
                elif digit == 'C':
                    imgs[i] = img.img2
                elif digit == 'D':
                    imgs[i] = img.img3
                elif digit == 'E':
                    imgs[i] = img.img4
                elif digit == 'F':
                    imgs[i] = img.img5                                        
                else:
                    imgs[i] = img.img0
                if not imgs[i]:
                    raise "image "+str(digit)+" is missing"
            composite = images.composite([(imgs[0],0,0,1.0,0), 
                                          (imgs[1],15,0,0.8,0),
                                          (imgs[2],30,0,0.7,0),
                                          (imgs[3],45,0,0.6,0),
                                          (imgs[4],60,0,0.5,0),
                                          (imgs[5],75,0,0.4,0)
                                          ]
                                         , 90, 16)
                    
            return composite                           
        else:
            raise "null token"
        
    def get(self):
        values = {}
        try:
            img = NumberImage.queryByInfoKey(self.request.get('id'))
            if img:
                token = self.request.get('token')
                if token:
                    composite = self.createImage(img, token, str(img.key()))
                    self.response.headers['Content-Type'] = "image/png"
                    self.response.out.write(composite)
                else:                 
                    values['items'] = img  
            else:
                raise "ID not found"
        except:
            values['msg'] = 'Error'+str(sys.exc_info())
        self.outputTemplate(values, "main_view")       
            
                       

class UploadPage(BaseHandler):
    def get(self):
        values = {}
        values['id'] = self.getCookie('id')
        values['secret'] = self.getCookie('secret')
        self.outputTemplate(values, "upload_view")
        
    def post(self):
        values = {}
        try:
            info = db.get(self.request.get('id'))
            if info:
                if info.secret == self.request.get('secret'):
                    img = db.get(info.secret)
                    if not img:
                        img = NumberImage(information=info)
                    png = db.Blob(self.request.get('file'))
                    title = self.request.get('title').strip()
                    if title == '0':
                        img.img0 = png
                    elif title == '1':
                        img.img1 = png
                    elif title == '2':
                        img.img2 = png
                    elif title == '3':
                        img.img3 = png
                    elif title == '4':
                        img.img4 = png
                    elif title == '5':
                        img.img5 = png
                    elif title == '6':
                        img.img6 = png
                    elif title == '7':
                        img.img7 = png
                    elif title == '8':
                        img.img8 = png
                    elif title == '9':
                        img.img9 = png                        
                    else:
                        raise "The title must be '0' to '9'."
                    img.put()
                else:
                    raise "Wrong secret"
            else:
                raise "ID not found"
            values['msg'] = 'OK'
        except:
            values['msg'] = 'Error'+str(sys.exc_info())
        randomstr = self.request.remote_addr + str(time.time())
        values['mytoken'] = randomstr            
        self.outputTemplate(values, "main_view")       
        
class CodePage(BaseHandler):
    def get(self):
        values = {}
        values['id'] = self.getCookie('id')
        values['secret'] = self.getCookie('secret')
        self.outputTemplate(values, "code_view")
             
class TestPage(BaseHandler):
    def get(self):
        values = {}
        values['id'] = self.getCookie('id')
        values['secret'] = self.getCookie('secret')        
        self.outputTemplate(values, "test_view")

    
application = webapp.WSGIApplication([('/', MainPage),
                                      ('/requestkey', RequestKeyPage),
                                      ('/upload', UploadPage),
                                      ('/display', DisplayPage),
                                      ('/code', CodePage),
                                      ('/test', TestPage)
                                      ],
                                     debug=True)
    
def main():
    run_wsgi_app(application)

if __name__ == "__main__":
  main()